# coding=utf-8
import datetime
import time
from time import sleep

import smbus


def delay(time):
    sleep(time / 1000.0)


def delayMicroseconds(time):
    sleep(time / 1000000.0)


'''
LCD 显示屏
'''


class Screen():
    enable_mask = 1 << 2
    rw_mask = 1 << 1
    rs_mask = 1 << 0
    backlight_mask = 1 << 3

    data_mask = 0x00

    def __init__(self, cols=16, rows=2, addr=0x27, bus=1):
        self.cols = cols
        self.rows = rows
        self.bus_num = bus
        self.bus = smbus.SMBus(self.bus_num)
        self.addr = addr
        self.display_init()

    def enable_backlight(self):
        self.data_mask = self.data_mask | self.backlight_mask

    def disable_backlight(self):
        self.data_mask = self.data_mask & ~self.backlight_mask

    def cursorTo(self, row, col):
        offsets = [0x00, 0x40, 0x14, 0x54]
        self.command(0x80 | (offsets[row] + col))

    def clear(self):
        self.command(0x10)

    def println(self, line):
        for char in line:
            self.print_char(char)

    def print_char(self, char):
        char_code = ord(char)
        self.send(char_code, self.rs_mask)

    def command(self, value, delay=50.0):
        self.send(value, 0)
        delayMicroseconds(delay)

    def send(self, data, mode):
        self.write4bits((data & 0xF0) | mode)
        self.write4bits((data << 4) | mode)

    def write4bits(self, value):
        value = value & ~self.enable_mask
        self.expanderWrite(value)
        self.expanderWrite(value | self.enable_mask)
        self.expanderWrite(value)

    def expanderWrite(self, data):
        self.bus.write_byte_data(self.addr, 0, data | self.data_mask)

    def display_init(self):
        delay(1.0)
        self.write4bits(0x30)
        delay(4.5)
        self.write4bits(0x30)
        delay(4.5)
        self.write4bits(0x30)
        delay(0.15)
        self.write4bits(0x20)
        self.command(0x20 | 0x08)
        self.command(0x04 | 0x08, delay=80.0)
        self.clear()
        self.command(0x04 | 0x02)
        delay(3)

    def display_data(self, *args):
        '''
        显示函数，样例代码 最下面调用方式
        :param args:
        :return:
        '''
        self.clear()
        for line, arg in enumerate(args):
            self.cursorTo(line, 0)
            self.println(arg[:self.cols].ljust(self.cols))

    def displayData(self, data):
        '''
        显示数据
        :param data: 数据
        :return:
        '''
        self.enable_backlight()
        self.display_data(data, data[-1:1:])


if __name__ == "__main__":
    '''
    样例代码，调用方式需要初始化对象，并调用screen的display_data方法
    '''
    screen = Screen(bus=1, addr=0x27, cols=16, rows=1)
    line = "we make the future ! PI TOP"
    cn = "3C°"
    screen.enable_backlight()
    while True:
        date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        print(date)
        # 下面是文字显示在上半部屏幕的使用方法
        # 将时间date显示在上半屏幕中
        screen.display_data(date, date[-1::])  # 第一个参数是上半屏的意思，第二个参数是下半屏幕的意思
        sleep(1)
        # 上下屏显示相同文字
        screen.display_data(date, date[:-1:])  # 第一个参数是上半屏的意思，第二个参数是下半屏幕的意思
        sleep(1)
        # 显示在上半屏，文字动态化
        screen.display_data(date, date[::-1])  # 第一个参数是上半屏的意思，第二个参数是下半屏幕的意思
        sleep(1)
        # 下面是文字显示在下半部屏幕的使用方法
        # 将时间date显示在下半屏幕中
        screen.display_data(date[-1::], date)  # 第一个参数是上半屏的意思，第二个参数是下半屏幕的意思
        sleep(1)
        # 上下屏显示相同文字
        screen.display_data(date[:-1:], date)  # 第一个参数是上半屏的意思，第二个参数是下半屏幕的意思
        sleep(1)
        # 显示在下半屏，文字动态化
        screen.display_data(date[::-1], date)  # 第一个参数是上半屏的意思，第二个参数是下半屏幕的意思
        sleep(1)
